home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 1
/
Precision Software Applications Silver Collection Volume One (PSM) (1993).iso
/
tutor
/
modula12.exe
/
CHAP15.TXT
< prev
next >
Wrap
Text File
|
1988-10-26
|
14KB
|
322 lines
Chapter 15 - Concurrency
PREREQUISITES FOR THIS MATERIAL
In order to understand this material you should have a
good grasp of the material in Part I of this tutorial and at
least a cursory knowledge of the material in chapter 14
concerning the pseudo module SYSTEM and especially the ADR
and SIZE functions.
WHAT IS CONCURRENCY
True concurrency is when two processes are taking place
at exactly the same time with neither affecting the other in
a degrading way. This is possible in many areas of your
life, such as when the Grandfather clock is running at the
same time as the furnace and the television set. These are
different processes all running at the same time. In the
field of computers, true concurrency requires at least two
separate processors that are running completely separate
programs or different parts of the same program.
Usually, when computers are said to be running
concurrent processes, reference is being made to a time
sharing situation in which two or more programs are swapped
in and out of the computer at a rapid rate, each getting a
small slice of time, a millisecond being typical. Each
process appears to be running constantly but is in fact only
running a small part of the time, sort of stuttering. The
swapping in and out is taking place so fast that, to the
casual user, it appears that the entire computer is working
on only his program.
WHAT IS MODULA-2 CONCURRENCY?
The process in Modula-2, which is called concurrency,
is neither of the above, and it should probably not be
called concurrency. It is a new way to call and return from
procedures, and although it is possible to use this new
method of procedure linkage to simulate something that looks
like concurrent processes, it is not true concurrency. It
is a part of the language, and a useful part, so we will
cover it in this chapter.
OUR FIRST COROUTINE
Load and display the program named COROUT.MOD for our
first look at this new technique. Without lots of
explanation, there are lots of new items IMPORTED and a few
variables defined, the most interesting being the three that
are defined as PROCESS type. These will be the three
processes we will use in this example. Next, there are two
PROCEDURES which define what the coroutines will do. It
Page 94
Chapter 15 - Concurrency
must be noted that these PROCEDURES are not allowed to have
any formal parameters in their headers. Finally we come to
the main program which is where we will start to define how
to use the coroutines.
First, in the main program, we call "NEWPROCESS" which
loads a new process without running it. We give it the
name of the procedure where the process can be found, and
give the system a workspace by assigning a previously
defined array to it. This is done by giving the system the
address and the size of the array. Finally, we give it a
name by which we can call the process. It must be noted
that the workspace must be sufficient for the new process to
store all of its variables, so give the process a generous
workspace. If it is too small, a runtime error will be
generated. We then load a second process in preparation for
running the program by calling NEWPROCESS again.
HOW DO WE GET IT STARTED?
When we began the main program, we actually loaded and
started a process, the one we are presently executing. We
have done this for every program in this tutorial so far but
paid no attention to it as far as referring to it as a
process. We have not given our running process a name yet,
but we will when we leave it because we have defined another
PROCESS type variable named "main". To start the next
process we use the TRANSFER function with the name of the
process we wish to terminate and the one we wish to start.
This is illustrated in line 43 from which we jump to line 15
in the process named "Process1". In Process1 we begin a FOR
loop where we write a string and a cardinal number then when
"Index" exceeds 2, we do another TRANSFER, this time from
Process1 to Process2. Thus we jump from line 19 in one
procedure to line 31 in another where we begin an infinite
loop. We print another string in line 32 and once again do
a TRANSFER from line 33 to somewhere. The place where we go
at this point is what makes the coroutines different from
the standard procedure.
WHERE DO WE GO WHEN WE RETURN TO A COROUTINE?
Instead of jumping to the beginning of the procedure
again, which would be line 15 in this example, we return to
the statement following the one we left from. In this case
we will return from line 33 to line 20 and complete the loop
we started earlier. When Index is increased to 4, we will
once again TRANSFER control from line 19 to "Process2", but
instead of jumping to line 31 we will return where we left
off there at line 34. That loop will complete, and we will
once again return to line 20. When the FOR loop in
Page 95
Chapter 15 - Concurrency
"Process1" finishes, we execute lines 24 and 25 then the
TRANSFER in line 26 will return us to the main module body
where we will arrive at line 44 and complete the last two
write statements and do a normal exit to the operating
system.
Rather than a technical discussion of how to use
coroutines, this example was defined step by step. If it
was not clear, reread the entire description until you
understand it. There is really nothing else there is to
know about coroutines other than that knowledge gained by
experience in using them, which is true of any new
principle in computer programming or any other facet of
life.
WHAT WAS ALL THAT ABOUT?
The thing that is really different about coroutines is
the fact that they are both (or all three or more) loaded
into the computers memory and they stay loaded for the life
of the program. This is not true of normal procedures. It
is transparent to you, but procedures are not all simply
loaded into the computer and left there, they are
dynamically allocated and started as they are called. That
is why variables are not saved from one invocation of a
procedure to the next. The variables within a process are
loaded once, and stay resident for the life of the program.
In the example program on your monitor, all three
processss including the main program are loaded and none is
really the main program since any of the programs have the
ability to call the others.
Load and display COROUT2.MOD for the second example
with coroutines. This program is identical with the last
except that two lines are removed from the first process and
placed in a normal procedure which is called from line 22 to
illustrate that some of the code can be placed outside of
the coroutine process to make the resident part smaller.
The implication here is that you could have a four way
coprocess going on, each one of which had a very small
resident portion, and each one of which called some huge
regular procedures. In fact, there is no reason why two or
more of the coprocesses could not call the same normal
procedure.
Study this program until you understand the
implications, then compile and run it to see that it does
exactly the same thing as the last program.
Page 96
Chapter 15 - Concurrency
HOW ABOUT THREE PROCESSES?
Load and display COROUT3.MOD for an example with three
concurrent processes. This program is identical to the
first program with the addition of another process. In this
program, process 1 calls process 2, which calls process 3,
which once again calls process 1. Thus the same loop is
traversed but with one additional stop along the way. It
should be evident to you that there is no reason why this
could not be extended to any number of processes each
calling the next or in any looping scheme you could think up
provided of course that it had some utilitarian purpose.
WHAT IS THE BIG DIFFERENCE?
Actually, the big difference between real concurrent
processing and what this is doing is in the division of time
and in who, or what, is doing the division. In real
concurrent processing, the computer hardware is controlling
the operation of the processing and allocating time slots to
the various processes. In the pseudo concurrent processing
we are doing, it is the processes themselves that are doing
the time allocation leading to the possibility that if one
of the processes went bad, it could tie up all of the
resources of the system and no other process could do
anything. You could consider it a challenge to write a
successful system that really did share time and resources
well.
The important thing to consider about this technique is
that it is not a major breakthrough in a programming
language, but one additional tool available in Modula-2 that
is not available in the other popular languages such as
Pascal, C, Fortran, or BASIC.
ONE MORE INFINITE EXAMPLE OF CONCURRENCY
Load and display the program named INFINITE.MOD for
another example of a program with concurrency. In this
program, three processes are created and control is
transferred to the first one after which they call each
other in a loop with no provision for ever returning to the
main program. The computer will continually loop around the
three processes checking the printer, the keyboard, and the
system clock to see if they need servicing. It must be
pointed out that it would be a simple matter to include all
three checks in a single loop in the main program and do
away with all of this extra baggage. This method had one
advantage over the simple loop and that is the fact that
each coprocess can have its own variables which cannot be
affected by the operation of the other processes and yet are
Page 97
Chapter 15 - Concurrency
all memory resident at all times.
This program can be compiled and run but it will
execute forever since it has no way to stop it. You can
stop it because it is writing to the monitor and therefore
will be checking the control-break combination. Simply hit
control-break and the program will be terminated by the
operating system. It should be mentioned that if this
technique were used in a real situation, it would probably
not be writing to the monitor continually.
IS THIS REALLY USEFUL?
In a situation where you needed to service interrupts in
some prescribed and rapid fashion, a technique involving
Modula-2 concurrency could prove to be very useful. There
are other procedures available in Modula-2 to aid in writing
a pseudo-concurrent program but they are extrememly advanced
and would require an initimate knowledge of your particular
systems hardware, especially the interrupt system.
Since using these techniques are extremely advanced
programming techniques, they will not be covered here. They
are beyond the scope of this tutorial. It would be to your
advantage to study them and know that they exist, then
someday you may find that they fill the bill and greatly
simplify some particular programming problem.
Page 98